if restart ==1
    restart=0;
    epoch=1;
    
    % Initializing symmetric weights and biases. 
    vishid_user = 0.01*randn(num_items*5, numhid_user);
    vishid_item = 0.01*randn(num_users*5, numhid_item);
    hidbiases_user = zeros(1,numhid_user);
    hidbiases_item = zeros(1,numhid_item);
    visbiases_user  = zeros(1,num_items*5);
    visbiases_item  = zeros(1,num_users*5);

    poshidprobs_user = zeros(num_users,numhid_user);
    poshidprobs_item = zeros(num_items,numhid_item);
    neghidprobs_user = zeros(num_users,numhid_user);
    neghidprobs_item = zeros(num_items,numhid_item);
    posprods_user    = zeros(num_items*5,numhid_user);
    posprods_item    = zeros(num_users*5,numhid_item);
    negprods_user    = zeros(num_items*5,numhid_user);
    negprods_item    = zeros(num_users*5,numhid_item);
    vishidinc_user  = zeros(num_items*5,numhid_user);
    vishidinc_item  = zeros(num_users*5,numhid_item);
    hidbiasinc_user = zeros(1,numhid_user);
    hidbiasinc_item = zeros(1,numhid_item);
    visbiasinc_user = zeros(1,num_items*5);
    visbiasinc_item = zeros(1,num_users*5);

    
    count_movie_rate_times = sum(rate_matrix_user);
    for m=1:size(count_movie_rate_times,2)/5
        tmp_sum = sum(count_movie_rate_times(1,m*5-5+1:m*5));
        for n=1:5
            if count_movie_rate_times(1,m*5-5+n)~=0
                visbiases_user(1,m*5-5+n) = log(count_movie_rate_times(1,m*5-5+n)/(0.0+tmp_sum));
            else
                visbiases_user(1,m*5-5+n) = 0.0;
            end
        end
    end
    
    count_movie_rate_times = sum(rate_matrix_item);
    for m=1:size(count_movie_rate_times,2)/5
        tmp_sum = sum(count_movie_rate_times(1,m*5-5+1:m*5));
        for n=1:5
            if count_movie_rate_times(1,m*5-5+n)~=0
                visbiases_item(1,m*5-5+n) = log(count_movie_rate_times(1,m*5-5+n)/(0.0+tmp_sum));
            else
                visbiases_item(1,m*5-5+n) = 0.0;
            end
        end
    end
end

posvisact_user = sum(rate_matrix_user);
posvisact_item = sum(rate_matrix_item);



for epoch = epoch:maxepoch
    %%%%%%%%% START User POSITIVE PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    poshidprobs_user = 1./(1 + exp(-rate_matrix_user*vishid_user - repmat(hidbiases_user,num_users,1)));    
        
    posprods_user    = rate_matrix_user' * poshidprobs_user;
    poshidact_user   = sum(poshidprobs_user);
    
    
    %%%%%%%%% END OF POSITIVE PHASE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    poshidstates_user = poshidprobs_user > rand(num_users,numhid_user);

    %%%%%%%%% START NEGATIVE PHASE%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    negdata_user = poshidstates_user*vishid_user' + repmat(visbiases_user,num_users,1);
    
    for m=1:num_users
        reshap = reshape(negdata_user(m,:),5, num_items);
        reshap = exp(reshap - repmat(max(reshap), 5, 1));
        reshap = reshap./repmat(sum(reshap), 5, 1);
        negdata_user(m,:) = reshape(reshap, 1, 5*num_items);
    end
    negdata_user = negdata_user.*rate_matrix_template_user;
    
    
    
    %%%%%%%%% START Item POSITIVE PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    poshidprobs_item = 1./(1 + exp(-rate_matrix_item*vishid_item - repmat(hidbiases_item,num_items,1)));    
        
    posprods_item    = rate_matrix_item' * poshidprobs_item;
    poshidact_item   = sum(poshidprobs_item);
    
    
    %%%%%%%%% END OF POSITIVE PHASE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    poshidstates_item = poshidprobs_item > rand(num_items,numhid_item);

    %%%%%%%%% START NEGATIVE PHASE%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    negdata_item = poshidstates_item*vishid_item' + repmat(visbiases_item,num_items,1);
    
    for m=1:num_items
        reshap = reshape(negdata_item(m,:),5, num_users);
        reshap = exp(reshap - repmat(max(reshap), 5, 1));
        reshap = reshap./repmat(sum(reshap), 5, 1);
        negdata_item(m,:) = reshape(reshap, 1, 5*num_users);
    end
    negdata_item = negdata_item.*rate_matrix_template_item;
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%%%%                prepare for average                   %%%%%%%%%%
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    b = mat2cell(negdata_user, num_users, ones(1, num_items)*5);
    tmp_user = cat(1,b{:});
    %tmp_user = reshape(dd, num_users, num_items, 5);
    
    t = negdata_item';
    p = reshape(t, 5, num_items*num_users);
    tmp_item = p';
    
    tmp_avg = (tmp_user + tmp_item)/2;
    
    ff = mat2cell(tmp_avg, ones(1, num_items)*num_users);
    negdata_user = cat(2,ff{:});
    
    tt = reshape(tmp_avg', num_users*5, num_items);
    negdata_item = tt';
    
    %%%%%%%%%%%%%%% ready to cal negtive   %%%%%%%%%%%%%%%%%
    neghidprobs_user = 1./(1 + exp(-negdata_user*vishid_user - repmat(hidbiases_user,num_users,1)));  
    negprods_user  = negdata_user'*neghidprobs_user;
    neghidact_user = sum(neghidprobs_user);
    negvisact_user = sum(negdata_user); 
    
    neghidprobs_item = 1./(1 + exp(-negdata_item*vishid_item - repmat(hidbiases_item,num_items,1)));  
    negprods_item  = negdata_item'*neghidprobs_item;
    neghidact_item = sum(neghidprobs_item);
    negvisact_item = sum(negdata_item); 

    %%%%%%%%% END OF NEGATIVE PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       
    if epoch>5,
        momentum=finalmomentum;
    else
        momentum=initialmomentum;
    end;
    
    %%%%%%%%% UPDATE WEIGHTS AND BIASES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    vishidinc_user = momentum*vishidinc_user + epsilonw*( (posprods_user-negprods_user)/num_users - weightcost*vishid_user);
    visbiasinc_user = momentum*visbiasinc_user + (epsilonvb/num_users)*(posvisact_user-negvisact_user);
    hidbiasinc_user = momentum*hidbiasinc_user + (epsilonhb/num_users)*(poshidact_user-neghidact_user);
    
    vishidinc_item = momentum*vishidinc_item + epsilonw*( (posprods_item-negprods_item)/num_items - weightcost*vishid_item);
    visbiasinc_item = momentum*visbiasinc_item + (epsilonvb/num_items)*(posvisact_item-negvisact_item);
    hidbiasinc_item = momentum*hidbiasinc_item + (epsilonhb/num_items)*(poshidact_item-neghidact_item);
    
    vishid_user = vishid_user + vishidinc_user;
    visbiases_user = visbiases_user + visbiasinc_user;
    hidbiases_user = hidbiases_user + hidbiasinc_user;
    
    vishid_item = vishid_item + vishidinc_item;
    visbiases_item = visbiases_item + visbiasinc_item;
    hidbiases_item = hidbiases_item + hidbiasinc_item;
    %%%%%%%%%%%%%%%% END OF UPDATES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

   
    MAE

end;
